home *** CD-ROM | disk | FTP | other *** search
/ Aminet 3 / Aminet 3 - July 1994.iso / Aminet / misc / unix / dcalc1_2_c.Z / dcalc1_2_c
Encoding:
Text File  |  1994-01-11  |  19.9 KB  |  708 lines

  1. /* dcalc v1.1 -- fits files onto disks */
  2. /* written 23 Dec 1993 by Mark Baker */
  3. /* modified 6 Jan 1994 by Mark Baker (Bugfix, added extra features) */
  4. /* modified 11 Jan 94 by Mark Baker (more bugs fixed) */
  5. /* This source code may be freely distributed and modified,
  6.    but may not be used in a commercial product without the author's
  7.    permission.  A small charge for media and copying is allowed ( $6 max ). */
  8. /* For usage, type dcalc -help when compiled. 
  9.    This should be simple ANSI C.  It calls the unix utilities
  10.    ls, rm and mv.  You will have to alter the source if your system
  11.    uses different commands.  Just alter the defines below.. */
  12.    
  13. #define    SYS_LIST    "ls -l"
  14. #define    SYS_DELETE    "rm"
  15. #define SYS_RENAME    "mv"
  16.  
  17. /* includes */
  18. #include    <stdio.h>
  19. #include    <stdlib.h>
  20. #include    <string.h>
  21. #include    <ctype.h> 
  22.  
  23. /* defines */
  24. enum {FALSE, TRUE};
  25. #define    ONE_K    1024L
  26. #define IBM_DD    720L * ONE_K
  27. #define IBM_HD    1440L * ONE_K
  28. #define DEF_SIZE IBM_DD
  29. #define Lnext(ptr)    ptr = ptr->next
  30.  
  31. /* structures and typedefs */
  32. struct    ilist            /* include list type */
  33. {
  34.     char    *pattern;    /* pattern to include */
  35.     struct ilist    *next;    /* next */
  36. };
  37.  
  38. struct    elist            /* exclude list type */
  39. {
  40.     char    *pattern;    /* pattern to exclude */
  41.     struct elist    *next;    /* next */
  42. };
  43.  
  44. struct    plist            /* path list type */
  45. {
  46.     char    *path;        /* path */
  47.     struct plist    *next;    /* next */
  48. };
  49.  
  50. struct    flist            /* file list type */
  51. {
  52.     char    *name;        /* file name */
  53.     char    *path;        /* path */
  54.     long    size;        /* size in bytes */
  55.     struct flist    *next;    /* next */
  56. };
  57.  
  58. struct    opt            /* options list type */
  59. {
  60.     long    disk_size;    /* size of disks, in bytes */
  61.     long    reserved;    /* size in bytes reserved for system */
  62.     int    output_to_file;    /* flag - send output to file */
  63.     int    include_list;    /* flag - use include list */
  64.     int    exclude_list;    /* flag - use exclude list */
  65.     int    rename_files;    /* flag - rename files */
  66.     int    backup;        /* flag - use BACKUP mode */
  67.     char    *output_filename;    /* file to output to */
  68.     struct ilist    *inc_list;    /* include list */
  69.     struct elist    *exc_list;    /* exclude list */
  70.     struct plist    *path_list;    /* path list */
  71. };    
  72.  
  73. struct    disklist        /* disk list type */
  74. {
  75.     struct flist    *files;    /* list of files on disk */
  76.     long    free_space;    /* free space left */
  77.     long    used_space;    /* space used on disk */
  78.     float    perc_used;    /* space used as a % */
  79.     int    number;        /* number of the disk */
  80.     struct disklist    *next;    /* next */
  81. };
  82.  
  83. /* function prototypes */
  84. int    main(int argc, char *argv[]);
  85. void    get_options(int argc, char *argv[]);
  86. struct flist    *get_files(void);
  87. struct disklist    *fit_files(struct flist *file_list_top);
  88. void    show_results(struct disklist *disk_list_top);
  89.  
  90. /* global variables */
  91. struct opt    options;    /* option list */
  92.  
  93. /* calculator program to add up size of files to fit on IBM disks */
  94. int    main(int argc, char *argv[])
  95. {
  96.     struct flist    *file_list;
  97.     struct disklist    *disk_list;
  98.     
  99.     /* get options from command line */
  100.     get_options(argc, argv);
  101.     
  102.     /* load in filenames */
  103.     file_list = get_files();
  104.     
  105.     /* fit files onto disk */
  106.     disk_list = fit_files(file_list);
  107.     
  108.     /* output results */
  109.     show_results(disk_list);
  110.     
  111.     return(0);
  112. }
  113.  
  114. int    str_match(char *src, char *match);
  115.  
  116. void    get_options(int argc, char *argv[])
  117. {
  118.     int    count, show_usage = FALSE;
  119.     long    num = 0;
  120.     float    ftmp;
  121.     char    *opt, *c;
  122.     struct plist    *cur_path;
  123.     struct elist    *cur_excl;
  124.     struct ilist    *cur_incl;
  125.     
  126.     /* clear options */
  127.     options.disk_size = 0;
  128.     options.output_to_file = FALSE;
  129.     options.include_list = FALSE;
  130.     options.exclude_list = TRUE;
  131.     options.rename_files = FALSE;
  132.     options.backup = FALSE;
  133.     options.output_filename = NULL;
  134.     options.inc_list = NULL;
  135.     options.exc_list = (struct elist *)malloc(sizeof(struct elist));
  136.     options.path_list = NULL;
  137.     options.reserved = -1;
  138.     
  139.     cur_excl = options.exc_list;
  140.     cur_excl->pattern = "dcalc.tmp";
  141.     cur_excl->next = NULL;
  142.     
  143.     for (count = 1; count < argc; ) 
  144.       if (argv[count][0] == '-') 
  145.       {
  146.          /* an option */
  147.          opt = argv[count] + 1;
  148.          count++;
  149.          /* flags */
  150.          if (str_match(opt,"?"))
  151.          {
  152.               show_usage = TRUE;
  153.          }
  154.          else if (str_match(opt,"hd"))
  155.          {
  156.               options.disk_size = IBM_HD ;
  157.          }
  158.          else if (str_match(opt,"dd"))
  159.          {
  160.               options.disk_size = IBM_DD ;
  161.          }
  162.          else if (str_match(opt,"help"))
  163.          {
  164.                show_usage = TRUE;
  165.          }
  166.          else if (str_match(opt,"rename"))
  167.          {
  168.               options.rename_files = TRUE;
  169.          }
  170.          else if (str_match(opt,"backup"))
  171.          {
  172.               options.backup = TRUE;
  173.               options.rename_files = FALSE;
  174.          }
  175.          if ((count < argc) && (argv[count][0] != '-'))
  176.          {
  177.             if (str_match(opt,"s"))
  178.             {
  179.                for (c = argv[count] ; *(c+1) != '\0' ; c++) ;
  180.                if (toupper(*c) == 'K') 
  181.                {
  182.                  *c == '\0';
  183.                  if (sscanf(argv[count],"%d", &num)) 
  184.                  {
  185.                      options.disk_size = num * ONE_K;
  186.                      count++;
  187.                  }    
  188.                }
  189.                else if (toupper(*c) == 'M')
  190.                {
  191.                  *c == '\0';
  192.                  if (sscanf(argv[count],"%f", &ftmp))
  193.                  {
  194.                      options.disk_size = (long) (ftmp * (float)(ONE_K * ONE_K));
  195.                      count++;
  196.                  }
  197.                }
  198.                else if (sscanf(argv[count],"%d", &num))
  199.                 {
  200.                  options.disk_size = num;
  201.                  count++;
  202.                 }
  203.             }
  204.             else if (str_match(opt,"o"))
  205.             {
  206.                  options.output_to_file = TRUE;
  207.                  options.output_filename = argv[count];
  208.                  count++;
  209.              }
  210.             else if (str_match(opt,"ls"))
  211.             {
  212.                 /* add another path */
  213.                  if (options.path_list == NULL)
  214.                  {
  215.                      options.path_list = (struct plist *)malloc(sizeof(struct plist));
  216.                      cur_path = options.path_list;
  217.                  }
  218.                  else
  219.                  {
  220.                      cur_path->next = (struct plist *)malloc(sizeof(struct plist));
  221.                      Lnext(cur_path);
  222.                  }
  223.                  cur_path->path = argv[count];
  224.                  cur_path->next = NULL;
  225.             count++;
  226.             }
  227.             else if (str_match(opt,"in"))
  228.             {
  229.                 /* add to include list */
  230.                while((count < argc) && (argv[count][0] != '-')) 
  231.                {
  232.                    if (options.inc_list == NULL)
  233.                    {
  234.                     options.inc_list = (struct ilist *)malloc(sizeof(struct ilist));
  235.                      options.include_list = TRUE;
  236.                         cur_incl = options.inc_list;
  237.                     }
  238.                     else
  239.                     {
  240.                      cur_incl->next = (struct ilist *)malloc(sizeof(struct ilist));
  241.                      Lnext(cur_incl);
  242.                     }
  243.                     cur_incl->pattern = argv[count];
  244.                     cur_incl->next = NULL;
  245.                count++;
  246.             }    
  247.             }
  248.             else if (str_match(opt,"ex"))
  249.             {
  250.                 /* add to exclude list */
  251.                 while((count < argc) && (argv[count][0] != '-')) 
  252.                {
  253.                     cur_excl->next = (struct elist *)malloc(sizeof(struct elist));
  254.                     Lnext(cur_excl);
  255.                     cur_excl->pattern = argv[count];
  256.                     cur_excl->next = NULL;
  257.                count++;
  258.             }
  259.             }
  260.             else if (str_match(opt,"reserve"))
  261.             {
  262.                for (c = argv[count] ; *(c+1) != '\0' ; c++) ;
  263.                if (toupper(*c) == 'K') 
  264.                {
  265.                  *c == '\0';
  266.                  if (sscanf(argv[count],"%d", &num)) 
  267.                  {
  268.                      options.reserved = num * ONE_K;
  269.                      count++;
  270.                  }    
  271.                }
  272.                else if (toupper(*c) == 'M')
  273.                {
  274.                  *c == '\0';
  275.                  if (sscanf(argv[count],"%f", &ftmp))
  276.                  {
  277.                      options.reserved = (long) (ftmp * (float)(ONE_K * ONE_K));
  278.                      count++;
  279.                  }
  280.                }
  281.                else if (toupper(*c) == 'P')
  282.                {
  283.                  *c == '\0';
  284.                  if (options.disk_size == 0) options.disk_size = IBM_DD;
  285.                  if (sscanf(argv[count],"%f",&ftmp))
  286.                  {
  287.                 options.reserved = (long)(ftmp * (float)(options.disk_size));
  288.                 count++;
  289.                  }
  290.                }
  291.                else if (sscanf(argv[count],"%d", &num))
  292.                 {
  293.                  options.reserved = num;
  294.                  count++;
  295.                 }
  296.             }
  297.          }
  298.       }
  299.       else
  300.       {
  301.          /* not an option.. must be path */
  302.          /* add to path list */
  303.          if (options.path_list == NULL)
  304.          {
  305.              options.path_list = (struct plist *)malloc(sizeof(struct plist));
  306.              cur_path = options.path_list;
  307.          }
  308.          else
  309.          {
  310.              cur_path->next = (struct plist *)malloc(sizeof(struct plist));
  311.              Lnext(cur_path);
  312.          }
  313.          cur_path->path = argv[count];
  314.          cur_path->next = NULL;
  315.          count++;
  316.       }
  317.     /* now put in defaults */
  318.     if (options.disk_size == 0) options.disk_size = IBM_DD ;
  319.     if (options.reserved == -1) options.reserved = options.disk_size / 100;
  320.     if (options.reserved >= options.disk_size)
  321.     {
  322.         printf("Error: cannot reserve more space than disk size!\n");
  323.         exit(1);
  324.     }
  325.     if (show_usage)
  326.     {
  327.         /* print the usage */
  328.         printf("Usage:  dcalc [ path ... ] [ option ... ]\n");
  329.         printf(" path = path to scan for files\n");
  330.         printf(" option is one of the following:\n");
  331.         printf("   -hd = fit onto IBM 1.44MB high density disks\n");
  332.         printf("   -dd = fit onto IBM 720K disks (default)\n");
  333.         printf("   -s NNN = fit onto disk of size NNN\n");
  334.         printf("   -reserve NNN = reserve NNN of the disk for filesystem, etc.\n");
  335.         printf("             (default is 1%% to be safer)\n");
  336.         printf("   -o file = send output to file\n");
  337.         printf("   -ls path ... = add more paths\n");
  338.         printf("   -in \"pat\" = include files matching pattern (* ? wild)\n");
  339.         printf("   -ex \"pat\" = exclude files matching pattern\n"); 
  340.         printf("   -rename = rename files for easy copying (A_file1 B_file2 ...) \n");
  341.         printf("   -backup = use MSDOS backup mode, fit files across disks\n");
  342.         printf("  NNN is I  for I     bytes (  400 ==     400 bytes)\n");
  343.         printf("         Ik for I kilobytes (   1k ==    1024 bytes)\n");
  344.         printf("         Fm for F megabytes ( 1.4m == 1048576 bytes)\n");
  345.         printf("         Fp for F %% of disk space (cannot be used with -s)\n");
  346.         printf(" I is any integer (whole number), F any float (real number)\n");  
  347.     }
  348. }
  349.  
  350. int    pattern_match(char *str, char *pat);
  351. struct flist    *read_file_data_from_directory(char *path, 
  352.         struct flist *file_next);
  353.  
  354. struct flist    *get_files(void)
  355. {
  356.     /* load in files from directories specified in path_list */
  357.     struct plist    *path_ptr=NULL;
  358.     struct flist    *file_list_top;
  359.     
  360.     if (options.path_list != NULL)
  361.     {
  362.       for (path_ptr = options.path_list; path_ptr != NULL; Lnext(path_ptr))
  363.       {
  364.         file_list_top = read_file_data_from_directory(path_ptr->path,
  365.           file_list_top);
  366.       }
  367.     }
  368.     else
  369.     {
  370.     /* default, scan current directory only */
  371.       file_list_top = read_file_data_from_directory("",file_list_top);
  372.     }
  373.     
  374.     return(file_list_top);
  375. }
  376.  
  377. struct flist    *read_file_data_from_directory(char *path, 
  378.         struct flist *file_top)
  379.     /* read in and append file data to list */
  380.     char     temp[200],line[100];
  381.     char    *path_name, *c;
  382.     FILE    *fptr;
  383.     char    perm[10], dum[20], name[50];
  384.     struct ilist    *inc_ptr;
  385.     struct elist    *exc_ptr;
  386.     struct flist    *file;
  387.     long    size = 0;
  388.     int    num,match;
  389.     
  390.     path_name = (char *) malloc (strlen(path)+1);
  391.     strcpy(path_name, path);
  392.     sprintf(temp,"%s %s > dcalc.tmp", SYS_LIST, path);
  393.     system(temp);
  394.     fptr = fopen("dcalc.tmp","r");
  395.     if (fptr == NULL)
  396.     {
  397.       printf("Error opening dcalc.tmp\n");
  398.       exit(1);
  399.     }
  400.     /* you might have to change this next bit if the format of your
  401.      directory listing differs from the standard "ls -l" command */ 
  402.     while(fgets(line,100,fptr))
  403.     {
  404.       num = sscanf(line,"%s%s%s%s%d%s%s%s%s",perm,dum,dum,dum,&size,
  405.           dum,dum,dum,name);
  406.       if (num == 9)            /* removes "total nn" + other stuff */
  407.        if (perm[0] == '-')        /* files only, not directory etc.. */
  408.        {
  409.            /* if ls -F has been used, file name may end in special chars 
  410.              '/' directory and '@' link are screened out above, but '*'
  411.              must be removed from the file name, or errors will occur */
  412.            for (c = name; *c != '\0'; c++) if (*c == '*') *c == '\0';
  413.            /* apply filters.. ? means match any 1 char
  414.              * means match any chars up to . */
  415.            if (options.include_list)
  416.            {
  417.              /* include filter */
  418.           match = FALSE;
  419.              for (inc_ptr = options.inc_list; 
  420.                   inc_ptr != NULL; Lnext(inc_ptr)) 
  421.               if (pattern_match(name,inc_ptr->pattern))
  422.               {
  423.                 match = TRUE;
  424.                   break;
  425.               }
  426.           if (match == FALSE) size = -1;
  427.            }
  428.         if ((options.exclude_list) && (size >= 0))
  429.         {
  430.           /* exclude filter */
  431.           for (exc_ptr = options.exc_list;
  432.                exc_ptr != NULL; Lnext(exc_ptr)) 
  433.               if (pattern_match(name,exc_ptr->pattern) == TRUE) 
  434.               {
  435.                   size = -1;
  436.                   break;
  437.               }
  438.         }
  439.         if (size >= 0)    /* filters set size = -1 if reject */
  440.         {
  441.           if (file_top == NULL)
  442.           {
  443.               file_top = (struct flist *)malloc(sizeof(struct flist));
  444.               file = file_top;
  445.           }
  446.           else
  447.           {
  448.               file->next = (struct flist *)malloc(sizeof(struct flist));
  449.               Lnext(file);
  450.           }
  451.           file->name = (char *)malloc(strlen(name)+2);
  452.           strcpy(file->name,name);
  453.           file->size = size;
  454.           file->path = path_name;
  455.           file->next = NULL;
  456.         }
  457.        }
  458.     }
  459.     sprintf(name, "%s dcalc.tmp", SYS_DELETE);
  460.     system(name);        /* remove the temporary file */
  461.     return(file_top);
  462. }
  463.  
  464. struct disklist    *fit_files(struct flist *file_list_top)
  465. {
  466.     /* fit files onto as few disks as possible */
  467.     struct flist    *file, *biggest, *first_file = NULL, *top, *disk_file;
  468.     struct disklist    *disk, *first_disk = NULL, *tdisk;
  469.     int    num_to_place = 0;
  470.     long    space = 0, num_disks = 0;
  471.     long    disk_space = 0;
  472.     struct flist    *null_file;
  473.     
  474.     null_file = (struct flist *) malloc (sizeof(struct flist));
  475.     null_file->next = NULL;
  476.     null_file->name = NULL;
  477.     null_file->size = 0;
  478.     null_file->path = NULL;
  479.     
  480.     top = file_list_top;
  481.     disk_space = options.disk_size - options.reserved;
  482.     
  483.     if (options.backup) 
  484.     {
  485.         /* split files across discs */
  486.         space = 0;
  487.         for(file = top; file != NULL; Lnext(file) )
  488.             space += file->size;
  489.         num_disks = (space / disk_space) + 1;
  490.         space -= (num_disks - 1) * disk_space;
  491.         first_disk = (struct disklist *)malloc(sizeof(struct disklist));
  492.         disk = first_disk;
  493.         disk->free_space = options.disk_size - space;
  494.         disk->used_space = space;
  495.         disk->perc_used = (float)100 * (float)disk->used_space / (float)options.disk_size;
  496.     disk->next = NULL;
  497.     disk->files = top;
  498.     disk->number = (int)num_disks;
  499.     }
  500.     else
  501.     {
  502.         /* check that a file is not bigger than disk space */
  503.         for(file = top; file != NULL; Lnext(file), num_to_place++ )
  504.             if (file->size > disk_space)
  505.             {
  506.                 printf("File \"%s\" will not fit onto a single disk!\n", file->name);
  507.                 printf("Use -backup mode to split across disks\n");
  508.                 exit(1);
  509.             }
  510.     while(num_to_place-- > 0)
  511.     {
  512.       /* find biggest file that will fit in remaining space */
  513.       biggest = null_file;
  514.       while (biggest == null_file)
  515.       {
  516.         for (file = top; file != NULL; Lnext(file) )
  517.           if ((file->size <= space) && (file->size > biggest->size))
  518.               biggest = file;
  519.         if (biggest == null_file)
  520.         {
  521.           /* no more files will fit onto current disk, start a new one */
  522.           if (first_disk == NULL)
  523.           {
  524.               first_disk = (struct disklist *)malloc(sizeof(struct disklist));
  525.               disk = first_disk;
  526.           }
  527.           else
  528.           {
  529.               disk->used_space = disk_space - space;
  530.               disk->free_space = options.disk_size - disk->used_space;
  531.               disk->perc_used = (float)100.0 * (float)disk->used_space / (float)options.disk_size;
  532.               disk->files = first_file;
  533.               disk->next = (struct disklist *)malloc(sizeof(struct disklist));
  534.               Lnext(disk);
  535.               disk->number = (int)++num_disks;
  536.               disk->next = NULL;
  537.           }
  538.           first_file = NULL;
  539.           space = disk_space;
  540.         }
  541.       }
  542.       /* have found biggest file that fits on disk... move it onto disk */
  543.       if (first_file == NULL) 
  544.       {
  545.           first_file = biggest;
  546.           disk_file = biggest;
  547.       }
  548.       else
  549.       {
  550.           disk_file->next = biggest;
  551.           Lnext(disk_file);
  552.       }
  553.       /* unlink from list */
  554.       if (biggest == top)
  555.           top = biggest->next;
  556.       else {
  557.           for (file = top; file->next != biggest; Lnext(file)) ;
  558.           file->next = biggest->next;    
  559.       }
  560.       space -= disk_file->size;
  561.       disk_file->next = NULL;
  562.     }
  563.     if (space < options.disk_size) 
  564.     {
  565.       disk->used_space = disk_space - space;
  566.       disk->free_space = options.disk_size - disk->free_space;
  567.       disk->perc_used = (float)100.0 * (float)disk->used_space / (float)options.disk_size;
  568.       disk->files = first_file;
  569.       disk->number = (int)num_disks++;
  570.       disk->next = NULL;
  571.     }
  572.     else
  573.     {
  574.       for (tdisk = first_disk; tdisk->next != disk; Lnext(tdisk) ) ;
  575.       tdisk->next = NULL;
  576.       free(disk);
  577.     }
  578.     }
  579.     free(null_file);
  580.     return(first_disk);
  581. }
  582.  
  583. void    show_results(struct disklist *disk_list_top)
  584. {
  585.     /* show results.. */
  586.     struct disklist    *disk;
  587.     struct flist    *file;
  588.     char    disk_letter;
  589.     char    temp[100], temp2[100];
  590.     
  591.     printf(" Disk size is %d bytes, %d bytes reserved for system\n", 
  592.         options.disk_size, options.reserved); 
  593.     if (options.backup)
  594.     {
  595.       disk = disk_list_top;
  596.       printf("The backup takes up %d disk%c\n",disk->number,
  597.        (disk->number > 1 ? 's' : ' ') );
  598.       printf("The last disk is %.2f%% full ( %d used, %d free )\n",
  599.        disk->perc_used, disk->used_space, disk->free_space);
  600.       printf("Listing of files in backup:\n");
  601.       for(file = disk->files; file != NULL; Lnext(file) )
  602.          printf(" %s\n", file->name);
  603.     }
  604.     else if (options.rename_files)
  605.     {
  606.       printf("Files as split onto disks:\n");
  607.       for (disk = disk_list_top; disk != NULL; Lnext(disk) )
  608.       {
  609.          disk_letter = (char)('A' + disk->number);
  610.          printf("++ Disk %c ++ %d used, %d free, disk %.2f%% full ++\n",
  611.            disk_letter, disk->used_space, disk->free_space, 
  612.            disk->perc_used);
  613.          for(file = disk->files; file != NULL; Lnext(file) )
  614.          {
  615.              if (file->name[1] == '_')
  616.                  if (file->name[0] == disk_letter)  
  617.                  sprintf(temp,"%s",file->name);
  618.                  else
  619.                      sprintf(temp,"%c%s", disk_letter, (file->name + 1));
  620.              else
  621.                  sprintf(temp,"%c_%s", disk_letter, file->name);
  622.              printf(" %s >>> \t%s\n", file->name, temp);
  623.          } 
  624.       }
  625.       printf("Rename files? (y/n) : ");
  626.       scanf("%s",temp);
  627.       if (temp[0] == 'y')
  628.       {
  629.          for (disk = disk_list_top; disk != NULL; Lnext(disk) )
  630.          {
  631.            disk_letter = (char)('A' + disk->number);
  632.            for(file = disk->files; file != NULL; Lnext(file) )
  633.            {
  634.                  if (file->name[1] == '_')
  635.                      if (file->name[0] == disk_letter)
  636.                        sprintf(temp2,"%s",file->name);
  637.                      else
  638.                        sprintf(temp2,"%c%s",disk_letter, (file->name + 1));
  639.                  else
  640.                      sprintf(temp2,"%c_%s", disk_letter, file->name);
  641.           if (file->path[0] != '\0')
  642.            sprintf(temp,"%s %s/%s %s/%s", SYS_RENAME,
  643.             file->path, file->name,
  644.             file->path, temp2);
  645.               else
  646.                sprintf(temp,"%s %s %s", SYS_RENAME, file->name, temp2);
  647.           if ((file->name[0] == temp2[0]) && (file->name[1] == temp2[1]))
  648.               /* no change */ ;
  649.           else
  650.                   system(temp);
  651.               /*printf("%s\n",temp);*/
  652.            } 
  653.          }
  654.       }
  655.     }
  656.     else
  657.     {
  658.       printf("Files as split onto disks:\n");
  659.       for (disk = disk_list_top; disk != NULL; Lnext(disk) )
  660.        {
  661.          printf("++ Disk %c ++  %d used, %d free, disk %.2f%% full ++\n",
  662.           (char)('A' + disk->number), disk->used_space, disk->free_space, 
  663.            disk->perc_used);
  664.          for(file = disk->files; file != NULL; Lnext(file) )
  665.          {
  666.            printf(" %s\n", file->name);
  667.          }
  668.       }
  669.     }
  670. }
  671.  
  672. int    str_match(char *src, char *match)
  673. {
  674.     if (strlen(src) != strlen(match)) return(FALSE);
  675.     while (*src != '\0')
  676.     {
  677.       if (*src != *match) return(FALSE);
  678.       src++;
  679.       match++;
  680.     }
  681.     return(TRUE);
  682. }
  683.  
  684. int    pattern_match(char *str, char *pat)
  685. {
  686.     /* return TRUE if str matches pat */
  687.     for (;(*pat != '\0') && (*str != '\0'); pat++, str++)
  688.     {
  689.       if (*pat == '?') ;    /* dont try and match this one */
  690.       else if (*pat == '*')    /* search for char - after this one */
  691.       {
  692.         pat++;
  693.         if (*pat == '\0') return(TRUE);    /* '*' at end means don't match rest */ 
  694.         /* search for *pat */
  695.         while (*str != *pat)
  696.         {
  697.             if (*str == '\0') return(FALSE); /* ended with some left to match */
  698.             str++;
  699.         }
  700.       }
  701.       else     /* match normally */
  702.         if (*pat != *str) return(FALSE);
  703.     } 
  704.     if (*pat != *str) return(FALSE);    /* must end together */
  705.     return(TRUE);
  706. }
  707.